package com.yazdankhah.beans;

import com.yazdankhah.application.AppDAL;
import com.yazdankhah.application.Const;
import com.yazdankhah.dal.AYSql;
import com.yazdankhah.dal.Table;
import com.yazdankhah.messages.Message;
import com.yazdankhah.utils.TextDataTools;
import com.yazdankhah.utils.GenUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;

/**
 *
 * @author ahmad
 */
@Named
@SessionScoped
public class Bean implements Serializable {

  @Inject private User user;
  
  private Message msg;
  
  private String bookmarkText;
  
  private List<SelectItem> availableBMs = new ArrayList<>();
  
  private List<String> selectedBMs;

  private static String thisYear;

  private static String appVersion;

  private short chapter = 1;

  private short verse = 1;

  private short serial = 1;

  private Combo combo;

  private SubTrans subTrans;

  private String subTranslationCombine;

  private static final Logger logger = Logger.getLogger(Bean.class);


  public Bean() {
    
    //user = new User(100);
    
    //logger.info("The Bean is being initialized ...");

    Date today = new Date();
    thisYear = GenUtil.getYear(today);
    ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().
            getExternalContext().getContext();
    appVersion = servletContext.getInitParameter(Const.ContextKeys.APP_VERSION);
    
    //initializePage();

  } //constructor


  public String goToBookmark(AjaxBehaviorEvent event) {
    
    serial = Short.valueOf(selectedBMs.get(0));
    
//    logger.info("selectedBM = [" + selectedBMs + "]");
//    logger.info("Going to the serial: " + serial);
    
    goToSerial(serial);

    return null;
  } //method


  public String insertBookmark(AjaxBehaviorEvent event) {

    AppDAL.insertBean(new Bookmark(user.getUserId(), serial, bookmarkText));
    refreshBookmarks();
    
    return null;
  } //method
  
  
  public String deleteBookmark(AjaxBehaviorEvent event) {
    
    short ser = Short.valueOf(selectedBMs.get(0));

    AppDAL.deleteBookmarkByUserIdSerial(user.getUserId(), ser);
    refreshBookmarks();
    
    return null;
  } //method
  
  
  private void refreshBookmarks() {
    
    //logger.debug("UserId = " + user.getUserId());
    
    List<Bookmark> bookmarkList = AppDAL.getBookmarks(user.getUserId());
    availableBMs = new ArrayList<>();
    
    for (Bookmark bookmark : bookmarkList) {
      short ser = bookmark.getSerial();
      VerseAddr vaddr = TextDataTools.getVerseAddr(ser);
      short chap = vaddr.getChapter();
      short vers = vaddr.getVerse();
      String bMarkStr = chap + ":" + vers + ": " + bookmark.getDescr();
      availableBMs.add(new SelectItem(ser, bMarkStr));
      bookmarkText = "";
    }
  } //method
  
  

  @PostConstruct
  private void initializePage() {
    
   refreshBookmarks();

    LeftOff leftOff = AppDAL.getCurrentLeftOff(user.getUserId());
    
    if (leftOff == null) {
      logger.info("The leftOff is empty. Trying to insert the default chapter and verse.");
      setDefaultLeftOffPoint();
      
    } else {
      logger.info("The leftOff has a record. Trying to go to where we left off ...");
      setCurrentLeftOffPoint(leftOff);
    }
    
    combo = TextDataTools.lookupQuran(chapter, verse, serial);
    
  } //method


  private void setDefaultLeftOffPoint() {

    chapter = Const.DEFAULT_CHAPTER;
    verse   = Const.DEFAULT_VERSE;
    serial  = TextDataTools.convertToSerial(chapter, verse, serial);

    LeftOff leftOff = new LeftOff(user.getUserId(), serial);
    boolean res = AppDAL.insertBean(leftOff);
    if (!res)
      logger.error("Couldn't insert the appropriate record into leftOff table.");
      
  } //method


  private void setCurrentLeftOffPoint(LeftOff leftOff) {

    serial = leftOff.getSerial();
    VerseAddr vAddr = TextDataTools.getVerseAddr(serial);
    chapter = vAddr.getChapter();
    verse = vAddr.getVerse();
    
  } //method


  public String logout() {

    boolean res = AppDAL.deleteLeftOffByUserId(user.getUserId());
    LeftOff leftOff = new LeftOff(user.getUserId(), serial);
    res = AppDAL.insertBean(leftOff);
    
    //FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    
    return Const.URLs.APP_HOME + "?faces-redirect=true";
  } //method
  
  


  public String exit4() {

    boolean isTransaction = false;
    String sqlStr = TextDataTools.lookupSql("delete.leftOff.by.userId");
    if (sqlStr.isEmpty()) {
      logger.error("The following SQL string was not found: delete.leftOff.by.userId");
    }
    
    AYSql q = new AYSql(sqlStr, user.getUserId());
    //logger.debug("userId = " + userId);
    boolean res = q.executeDDL(isTransaction);
    
    if (res) {
      logger.info("The specified record is deleted!");
    }
    
    LeftOff leftOff = new LeftOff(user.getUserId(), serial);
    q = new AYSql(leftOff, LeftOff.class);
    res = q.insert(isTransaction);
    
    if (res) {
      logger.info("The specified record is inserted!");
    }
    
    return Const.URLs.APP_HOME;
  } //method


  public String exit3() {

    boolean isTransaction = false;
    LeftOff leftOff = new LeftOff(user.getUserId());
    AYSql q = new AYSql(leftOff, LeftOff.class);
    boolean res = q.delete(isTransaction);
    
    if (res) {
      logger.info("The specified record is deleted!");
    }

    return Const.URLs.APP_HOME;
  } //method


  public String exit2() {

    String tabName = "bookmark";
    Table table = new Table(tabName);
    boolean isTransaction = false;
    boolean res = table.deleteAll(isTransaction);
    
    if (res) {
      logger.info("All records of bookmark are deleted!");
    }

    return Const.URLs.APP_HOME;
  } //method


  public String breakTranslations(AjaxBehaviorEvent event) {

    subTrans = new SubTrans(combo.getCombination());
    //subTranslationCombine = combo.getCombination();
    subTranslationCombine = subTrans.breakTranslations();

    //logger.debug("subTranslationCombine = {\n" + subTranslationCombine + "}");
    //UnicodeUtil.showUnicodeStringInfo(subTranslationCombine, logger);
    return null;
  } //method


  public String nextSubTranslations(AjaxBehaviorEvent event) {

    subTranslationCombine = subTrans.nextCombinedTranslations();
    //System.out.println("subTranslationCombine = [" + subTranslationCombine + "]");

    return null;
  } //method


  public String previousSubTranslations(AjaxBehaviorEvent event) {

    subTranslationCombine = subTrans.previousCombinedTranslations();
    //System.out.println("subTranslationCombine = [" + subTranslationCombine + "]");

    return null;
  } //method
  

  /**
   * Looks up the request verse by applying the chapter and verse
   * 
   * Precondition: the serial should be a number between 1 and Const.VERSE_NUM .
   * @param event the Ajax event
   * @return the outcome null to stay in wherever it is now.
   */
  public String lookupVerse(AjaxBehaviorEvent event) {
    
    serial = TextDataTools.convertToSerial(chapter, verse, serial);
    combo = TextDataTools.lookupQuran(serial);

    //System.out.println("quranVerse = [" + quranVerse + "]");
    return null;
  } //method


  public String lookupNextVerse(AjaxBehaviorEvent event) {

    if (serial + 1 >= Const.VERSE_NUM) return null;
    
    serial++;
    goToSerial(serial);

    return null;
  } //method


  private void goToSerial(short ser) {

    VerseAddr verseAddr = TextDataTools.getVerseAddr(ser);
    combo = TextDataTools.lookupQuran(ser);

    chapter = verseAddr.getChapter();
    verse = verseAddr.getVerse();

  } //method


  public String lookupPereviousVerse(AjaxBehaviorEvent event) {
    
    if (serial - 1 < 1) return null;
    
    serial--;
    goToSerial(serial);

    return null;
  } //method


  public short getLeft() {
    
//    logger.info("Number of verses in the getLeft = " + Const.VERSE_NUM);
//    logger.info("serial = " + this.serial);
//    logger.info("left = " + (short) (Const.VERSE_NUM - this.serial));
    
    return (short) (Const.VERSE_NUM - this.serial - (short) 1);
  }


  public short getChapter() {
    return chapter;
  }


  public void setChapter(short chapter) {
    this.chapter = chapter;
  }


  public short getVerse() {
    return verse;
  }


  public void setVerse(short verse) {
    this.verse = verse;
  }


  public short getSerial() {
    return serial;
  }


  public void setSerial(short serial) {
    this.serial = serial;
  }


  public Combo getCombo() {
    return combo;
  }


  public void setCombo(Combo combo) {
    this.combo = combo;
  }


  public String getSubTranslationCombine() {
    return subTranslationCombine;
  }


  public void setSubTranslationCombine(String subTranslationCombine) {
    this.subTranslationCombine = subTranslationCombine;
  }


  public String getThisYear() {
    return thisYear;
  }


  public String getAppVersion() {
    return appVersion;
  }


  public String getBookmarkText() {
    return bookmarkText;
  }


  public void setBookmarkText(String bookmarkText) {
    this.bookmarkText = bookmarkText;
  }


  public List<SelectItem> getAvailableBMs() {
    return availableBMs;
  }


  public List<String> getSelectedBMs() {
    return selectedBMs;
  }


  public void setSelectedBMs(List<String> selectedBMs) {
    this.selectedBMs = selectedBMs;
  }
  
  
} //method
